package com.li.puzzle;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.media.ThumbnailUtils;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.ImageView;

import java.util.Random;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    private int column = 5;
    private int row = 3;
    private boolean flag = false;
    private ImageView[][] mImageViews = new ImageView[row][column];
    private GridLayout mGridLayout;
    private int width, height;
    private Bitmap mBitmap;
    private ImageView mEmptyImage;
    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            changeByDir(msg.what);
            return false;
        }
    });
    private Button mBtnRandom;
    private int downX, downY;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.puzzle_2);
        int oldWidth=mBitmap.getWidth();
        float scale=(getResources().getDisplayMetrics().widthPixels*0.9f)/oldWidth;
        mBitmap= ThumbnailUtils.extractThumbnail(BitmapFactory.decodeResource(getResources(), R.drawable.puzzle_2)
                , (int) (oldWidth*scale), (int) (mBitmap.getHeight()*scale));
        mGridLayout = (GridLayout) findViewById(R.id.layout_grid);
        mBtnRandom = (Button) findViewById(R.id.btn_random);
        mBtnRandom.setOnClickListener(this);
        mGridLayout.setRowCount(row);
        mGridLayout.setColumnCount(column);


        width = mBitmap.getWidth() / column;
        height = mBitmap.getHeight() / row;
        init();
        mEmptyImage = new ImageView(this);
        mEmptyImage = mImageViews[0][0];
        mEmptyImage.setImageBitmap(null);
        combo(1000);

    }

    private void init() {
        //裁剪
        for (int i = 0; i < mImageViews.length; i++) {
            for (int j = 0; j < mImageViews[0].length; j++) {
                Bitmap bitmap = Bitmap.createBitmap(mBitmap, j * width, i * height, width, height);
                mImageViews[i][j] = new ImageView(MainActivity.this);
                mImageViews[i][j].setImageBitmap(bitmap);
                mImageViews[i][j].setPadding(2, 2, 2, 2);
                ImageTag imageTag = new ImageTag(i, j, bitmap);
                mImageViews[i][j].setTag(imageTag);
                imageTag.setPoint(new Point(i, j));
                mImageViews[i][j].setOnClickListener(this);
            }
        }
        //添加
        for (int i = 0; i < mImageViews.length; i++) {
            for (int j = 0; j < mImageViews[0].length; j++) {
                mGridLayout.addView(mImageViews[i][j]);
            }
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_random:
                flag = false;
                combo(100);
                break;
            default:
                flag = true;
                changePosition((ImageView) v, mEmptyImage);
                break;
        }

    }

    private void changePosition(ImageView imageView, ImageView emptyImage) {
        ImageTag imageTag = (ImageTag) imageView.getTag();
        ImageTag emptyTag = (ImageTag) emptyImage.getTag();
        int clickedX = imageTag.getX();
        int clickedY = imageTag.getY();
        int emptyX = emptyTag.getX();
        int emptyY = emptyTag.getY();

        if (canChange(clickedX, clickedY, emptyX, emptyY)) {
            emptyImage.setImageBitmap(imageTag.getBitmap());
            emptyTag.setBitmap(imageTag.getBitmap());
            mEmptyImage = imageView;
            imageView.setImageBitmap(null);

            //设置位置坐标变换
            Point clickPoint = imageTag.getPoint();
            Point emptyPoint = emptyTag.getPoint();
            int tmpX = emptyPoint.x;
            int tmpY = emptyPoint.y;
            emptyPoint.set(clickPoint.x, clickPoint.y);
            clickPoint.set(tmpX, tmpY);
            if (isCompleted() && flag) {
                new AlertDialog.Builder(MainActivity.this)
                        .setMessage("COMPLETE")
                        .setPositiveButton("OK", null)
                        .create()
                        .show();
            }


        }
    }

    private boolean canChange(int cX, int cY, int eX, int eY) {

        if (cX == eX && ((cY == eY + 1) || (cY == eY - 1))) {
            return true;
        }

        if (cY == eY && ((cX == eX + 1) || (cX == eX - 1))) {
            return true;
        }

        return false;
    }

    /**
     * 随机组合
     *
     * @param comboCount 组合次数
     */
    private void combo(int comboCount) {

        for (int i = 0; i < comboCount; i++) {
            //1:left 2:top 3:right 4:bottom
            int random = new Random().nextInt(1000);
            handler.sendEmptyMessage(random);
        }


    }

    private void changeByDir(int dir) {
        ImageTag imageTag = (ImageTag) mEmptyImage.getTag();
        int x = imageTag.getX();
        int y = imageTag.getY();
        ImageView imageView = null;
        dir = dir % 7;
        switch (dir) {
            case 1:
                if (y == mImageViews[0].length - 1) {
                    return;
                }
                imageView = mImageViews[x][y + 1];
                break;
            case 2:
                if (x == mImageViews.length - 1) {
                    return;
                }
                imageView = mImageViews[x + 1][y];
                break;
            case 3:
                if (y == 0) {
                    return;
                }
                imageView = mImageViews[x][y - 1];
                break;
            case 4:
                if (x == 0) {
                    return;
                }
                imageView = mImageViews[x - 1][y];
                break;
        }
        if (imageView != null) {
            changePosition(imageView, mEmptyImage);
        }

    }

    private boolean isCompleted() {
        for (int i = 0; i < mImageViews.length; i++) {
            for (int j = 0; j < mImageViews[0].length; j++) {
                ImageView imageView = mImageViews[i][j];
                ImageTag imageTag = (ImageTag) imageView.getTag();
                Point point = imageTag.getPoint();
                if (!point.equals(i, j)) {
                    return false;
                }
            }
        }

        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        flag=true;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getX();
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_UP:
                int upX = (int) event.getX();
                int upY = (int) event.getY();
                int dir;
                int offsetX = upX - downX;
                int offsetY = upY - downY;
                if (Math.abs(offsetX) > Math.abs(offsetY)) {
                    if (offsetX > 0) {
                        dir = 3;
                    } else {
                        dir = 1;
                    }
                } else {
                    if (offsetY > 0) {
                        dir = 4;
                    } else {
                        dir = 2;
                    }
                }
                changeByDir(dir);
                break;
        }
        return true;
    }


    class ImageTag {
        int x;
        int y;
        Bitmap bitmap;
        Point mPoint;

        ImageTag(int x, int y, Bitmap bitmap) {
            this.x = x;
            this.y = y;
            this.bitmap = bitmap;
        }

        public Point getPoint() {
            return mPoint;
        }

        public void setPoint(Point point) {
            mPoint = point;
        }

        public Bitmap getBitmap() {
            return bitmap;
        }

        public void setBitmap(Bitmap bitmap) {
            this.bitmap = bitmap;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }
    }
}